package com.iepacj.concurrency.ch4.two;

import com.iepacj.concurrency.ch4.one.SleepUtils;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by iEpac on 16/4/23.
 */
public class WaitNotify {

    private static Object lock = new Object();

    private static boolean flag = true;

    public static void main(String[] args) {

        new Thread(new Wait(), "WaitThread").start();

        SleepUtils.second(1);

        new Thread(new Notify(), "NotifyThread").start();

    }


    static class Wait implements Runnable {

        @Override
        public void run() {

            synchronized (lock) {
                while (flag) {

                    String msg = Thread.currentThread() + " flag is true, wait @ " +
                            new SimpleDateFormat("HH:mm:ss:sss").format(new Date());

                    System.out.println(msg);

                    try {
                        /**
                         * wait()方法调用后, 该线程进入waitting状态, 只有等待另外的线程通知或被中断才会返回
                         * 并且会释放这个对象上的锁
                         * 线程状态由ROUNNING变成WAITTING, 并将当前线程放入lock的等待队列中, 然后释放lock上的锁
                         */
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    msg = Thread.currentThread() + " wait后的代码执行 @ " + new SimpleDateFormat("HH:mm:ss:sss").format(new Date());
                    System.out.println(msg);
                }

                String msg = Thread.currentThread() + " flag is false, running @ " +
                        new SimpleDateFormat("HH:mm:ss:sss").format(new Date());
                System.out.println(msg);
            }


        }
    }

    static class Notify implements Runnable {

        @Override
        public void run() {

            synchronized (lock) {

                System.out.println(Thread.currentThread() + " hold lock, notify @ " + new SimpleDateFormat("HH:mm:ss:sss").format(new Date()));

                lock.notifyAll();

                flag = false;

                SleepUtils.second(5);
            }

            synchronized (lock) {

                System.out.println(Thread.currentThread() + " hold lock again, sleep @ " + new SimpleDateFormat("HH:mm:ss:sss").format(new Date()));

                SleepUtils.second(5);
            }

        }
    }


}


















